﻿/*
* jquery.splitter.js - two-pane splitter window plugin
*
* version 1.01 (01/05/2007) 
* 
* Dual licensed under the MIT and GPL licenses: 
*   http://www.opensource.org/licenses/mit-license.php 
*   http://www.gnu.org/licenses/gpl.html 
*/

/**
* The splitter() plugin implements a two-pane resizable splitter window.
* The selected elements in the jQuery object are converted to a splitter;
* each element should have two child elements which are used for the panes
* of the splitter. The plugin adds a third child element for the splitbar.
* 
* For more details see: http://methvin.com/jquery/splitter/
*
*
* @example $('#MySplitter').splitter();
* @desc Create a vertical splitter with default settings 
*
* @example $('#MySplitter').splitter({direction: 'h', accessKey: 'M'});
* @desc Create a horizontal splitter resizable via Alt+Shift+M
*
* @name splitter
* @type jQuery
* @param String options Options for the splitter
* @cat Plugins/Splitter
* @return jQuery
* @author Dave Methvin (dave.methvin@gmail.com)
*/
jQuery.fn.splitter = function(opts) {
    opts = jQuery.extend({
        type: 'v', 			// v=vertical, h=horizontal split
        activeClass: 'active', // class name for active splitter
        pxPerKey: 5, 		// splitter px moved per keypress
        tabIndex: 0, 		// tab order indicator
        accessKey: ''			// accelerator key for splitter
        //		initA  initB			// initial A/B size (pick ONE)
        //		minA maxA  minB maxB	// min/max pane sizes
    }, {
        v: {					// Vertical splitters:
            keyGrowA: 39, 	//	left arrow key
            keyShrinkA: 37, 	//	right arrow key
            cursor: "e-resize", //	double-arrow horizontal
            splitbarClass: "vsplitbar",
            eventPos: "pageX", set: "left",
            adjust: "width", offsetAdjust: "offsetWidth", adjSide1: "Left", adjSide2: "Right",
            fixed: "height", offsetFixed: "offsetHeight", fixSide1: "Top", fixSide2: "Bottom"
        },
        h: {					// Horizontal splitters:
            keyGrowA: 40, 	//	down arrow key
            keyShrinkA: 38, 	//	up arrow key
            cursor: "n-resize", //	double-arrow vertical
            splitbarClass: "hsplitbar",
            eventPos: "pageY", set: "top",
            adjust: "height", offsetAdjust: "offsetHeight", adjSide1: "Top", adjSide2: "Bottom",
            fixed: "width", offsetFixed: "offsetWidth", fixSide1: "Left", fixSide2: "Right"
        }
}[((opts || {}).type || 'v').charAt(0).toLowerCase()], opts || {});

        return this.each(function() {
            function startSplit(e) {
                splitbar.addClass(opts.activeClass);
                if (e.type == "mousedown") {
                    paneA._posAdjust = paneA[0][opts.offsetAdjust] - e[opts.eventPos];
                    jQuery(document)
					.bind("mousemove", doSplitMouse)
					.bind("mouseup", endSplit);
                }
                return true; // required???
            }
            function doSplitKey(e) {
                var key = e.which || e.keyCode;
                var dir = key == opts.keyGrowA ? 1 : key == opts.keyShrinkA ? -1 : 0;
                if (dir)
                    moveSplitter(paneA[0][opts.offsetAdjust] + dir * opts.pxPerKey);
                return true; // required???
            }
            function doSplitMouse(e) {
                moveSplitter(paneA._posAdjust + e[opts.eventPos]);
            }
            function endSplit(e) {
                splitbar.removeClass(opts.activeClass);
                jQuery(document)
				.unbind("mousemove", doSplitMouse)
				.unbind("mouseup", endSplit);
            }
            function moveSplitter(np) {
                // Constrain new position to fit pane size limits; 16=scrollbar fudge factor
                // TODO: enforce group width in IE6 since it lacks min/max css properties?
                np = Math.max(paneA._min + paneA._padAdjust, group._adjust - (paneB._max || 9999), 16,
				Math.min(np, paneA._max || 9999, group._adjust - splitbar._adjust -
					Math.max(paneB._min + paneB._padAdjust, 16)));

                // Resize/position the two panes and splitbar
                splitbar.css(opts.set, np + "px");
                paneA.css(opts.adjust, np - paneA._padAdjust + "px");
                paneB.css(opts.set, np + splitbar._adjust + "px")
				.css(opts.adjust, group._adjust - splitbar._adjust - paneB._padAdjust - np + "px");

                // IE fires resize for us; all others pay cash
                if (!jQuery.browser.msie) {
                    paneA.trigger("resize");
                    paneB.trigger("resize");
                }
            }
            function cssCache(jq, n, pf, m1, m2) {
                // IE backCompat mode thinks width/height includes border and padding
                jq[n] = jQuery.boxModel ? (parseInt(jq.css(pf + m1)) || 0) + (parseInt(jq.css(pf + m2)) || 0) : 0;
            }
            function optCache(jq, pane) {
                // Opera returns -1px for min/max dimensions when they're not there!
                jq._min = Math.max(0, opts["min" + pane] || parseInt(jq.css("min-" + opts.adjust)) || 0);
                jq._max = Math.max(0, opts["max" + pane] || parseInt(jq.css("max-" + opts.adjust)) || 0);
            }

            // Create jQuery object closures for splitter group and both panes
            var group = jQuery(this).css({ position: "relative" });
            var divs = jQuery(">div", group).css({
                position: "absolute", 			// positioned inside splitter container
                margin: "0", 					// remove any stylesheet margin or ...
                border: "0", 					// ... border added for non-script situations
                "-moz-user-focus": "ignore"		// disable focusability in Firefox
            });
            var paneA = jQuery(divs[0]); 	// left  or top
            var paneB = jQuery(divs[1]); 	// right or bottom

            // Focuser element, provides keyboard support
            var focuser = jQuery('<a href="javascript:void(0)"></a>')
			.bind("focus", startSplit).bind("keydown", doSplitKey).bind("blur", endSplit)
			.attr({ accessKey: opts.accessKey, tabIndex: opts.tabIndex });

            // Splitbar element, displays actual splitter bar
            // The select-related properties prevent unintended text highlighting
            var splitbar = jQuery('<div></div>')
			.insertAfter(paneA).append(focuser)
			.attr({ "class": opts.splitbarClass, unselectable: "on" })
			.css({ position: "absolute", "-khtml-user-select": "none",
			    "-moz-user-select": "none", "user-select": "none"
			})
			.bind("mousedown", startSplit);
            if (/^(auto|default)$/.test(splitbar.css("cursor") || "auto"))
                splitbar.css("cursor", opts.cursor);

            // Cache several dimensions for speed--assume these don't change
            splitbar._adjust = splitbar[0][opts.offsetAdjust];
            cssCache(group, "_borderAdjust", "border", opts.adjSide1 + "Width", opts.adjSide2 + "Width");
            cssCache(group, "_borderFixed", "border", opts.fixSide1 + "Width", opts.fixSide2 + "Width");
            cssCache(paneA, "_padAdjust", "padding", opts.adjSide1, opts.adjSide2);
            cssCache(paneA, "_padFixed", "padding", opts.fixSide1, opts.fixSide2);
            cssCache(paneB, "_padAdjust", "padding", opts.adjSide1, opts.adjSide2);
            cssCache(paneB, "_padFixed", "padding", opts.fixSide1, opts.fixSide2);
            optCache(paneA, 'A');
            optCache(paneB, 'B');

            // Initial splitbar position as measured from left edge of splitter
            paneA._init = (opts.initA == true ? parseInt(jQuery.curCSS(paneA[0], opts.adjust)) : opts.initA) || 0;
            paneB._init = (opts.initB == true ? parseInt(jQuery.curCSS(paneB[0], opts.adjust)) : opts.initB) || 0;
            if (paneB._init)
                paneB._init = group[0][opts.offsetAdjust] - group._borderAdjust - paneB._init - splitbar._adjust;

            // Set up resize event handler and trigger immediately to set initial position
            group.bind("resize", function(e, size) {
                // Determine new width/height of splitter container
                group._fixed = group[0][opts.offsetFixed] - group._borderFixed;
                group._adjust = group[0][opts.offsetAdjust] - group._borderAdjust;
                // Bail if splitter isn't visible or content isn't there yet
                if (group._fixed <= 0 || group._adjust <= 0) return;
                // Set the fixed dimension (e.g., height on a vertical splitter)
                paneA.css(opts.fixed, group._fixed - paneA._padFixed + "px");
                paneB.css(opts.fixed, group._fixed - paneB._padFixed + "px");
                splitbar.css(opts.fixed, group._fixed + "px");
                // Re-divvy the adjustable dimension; maintain size of the preferred pane
                moveSplitter(size || (!opts.initB ? paneA[0][opts.offsetAdjust] :
				group._adjust - paneB[0][opts.offsetAdjust] - splitbar._adjust));
            }).trigger("resize", [paneA._init || paneB._init ||
			Math.round((group[0][opts.offsetAdjust] - group._borderAdjust - splitbar._adjust) / 2)]);
        });
    };
